﻿//-----------------------------------------------------------
// Record an audio stream from the default audio capture
// device. The RecordAudioStream function allocates a shared
// buffer big enough to hold one second of PCM audio data.
// The function uses this buffer to stream data from the
// capture device. The main loop runs every 1/2 second.
//-----------------------------------------------------------

#include "pch.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <stdio.h>

#include <dshow.h>
#include <Windows.h>
#include <winerror.h>
#include <mmdeviceapi.h>
#include <Functiondiscoverykeys_devpkey.h>

#include <Audioclient.h>
#include <audiopolicy.h>
#include <complex>


// REFERENCE_TIME time units per second and per millisecond
#define REFTIMES_PER_SEC  10000000
#define REFTIMES_PER_MILLISEC  10000

#define EXIT_ON_ERROR(hres)  \
              if (FAILED(hres)) { goto Exit; }
#define SAFE_RELEASE(punk)  \
              if ((punk) != NULL)  \
                { (punk)->Release(); (punk) = NULL; }

const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
const IID IID_IAudioClient = __uuidof(IAudioClient);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);


std::vector<BYTE> body;

int counter = 20;

HRESULT RecordAudioStream(std::vector<BYTE> recorder)
{
	HRESULT hr;
	REFERENCE_TIME hnsRequestedDuration = REFTIMES_PER_SEC;
	REFERENCE_TIME hnsActualDuration;
	UINT32 bufferFrameCount;
	UINT32 numFramesAvailable;
	IMMDeviceEnumerator *pEnumerator = NULL;
	IMMDevice *pDevice = NULL;
	IAudioClient *pAudioClient = NULL;
	IAudioCaptureClient *pCaptureClient = NULL;
	WAVEFORMATEX *pwfx = NULL;
	UINT32 packetLength = 0;
	BOOL bDone = FALSE;
	BYTE *pData;
	DWORD flags;

	//创建多媒体设备枚举器
	hr = CoCreateInstance(
		CLSID_MMDeviceEnumerator, NULL,
		CLSCTX_ALL, IID_IMMDeviceEnumerator,
		(void**)&pEnumerator);
	EXIT_ON_ERROR(hr)

		//获取声卡接口
		hr = pEnumerator->GetDefaultAudioEndpoint(
			eCapture, eConsole, &pDevice);
	EXIT_ON_ERROR(hr)

		//通过声卡接口获取声卡客户端接口
		hr = pDevice->Activate(
			IID_IAudioClient, CLSCTX_ALL,
			NULL, (void**)&pAudioClient);
	EXIT_ON_ERROR(hr)

		//获取音频格式
		hr = pAudioClient->GetMixFormat(&pwfx);
	EXIT_ON_ERROR(hr)
		//初始化声卡客户端
		hr = pAudioClient->Initialize(
			AUDCLNT_SHAREMODE_SHARED,
			0,
			hnsRequestedDuration,
			0,
			pwfx,
			NULL);
	EXIT_ON_ERROR(hr)

		//获取缓冲区大小（有多少音频帧）
		hr = pAudioClient->GetBufferSize(&bufferFrameCount);
	EXIT_ON_ERROR(hr)

		//获取捕获客户端
		hr = pAudioClient->GetService(
			IID_IAudioCaptureClient,
			(void**)&pCaptureClient);
	EXIT_ON_ERROR(hr)

		// Notify the audio sink which format to use.
		//hr = pMySink->SetFormat(pwfx);
		EXIT_ON_ERROR(hr)

		// Calculate the actual duration of the allocated buffer.
		hnsActualDuration = (double)REFTIMES_PER_SEC *
		bufferFrameCount / pwfx->nSamplesPerSec;

	hr = pAudioClient->Start();  // Start recording.
	EXIT_ON_ERROR(hr)

		// Each loop fills about half of the shared buffer.
		while (counter > 0)
		{
			printf("正在读取数据包，剩余数据包数%d...\n", counter);
			// Sleep for half the buffer duration.
			Sleep(hnsActualDuration / REFTIMES_PER_MILLISEC / 2);

			hr = pCaptureClient->GetNextPacketSize(&packetLength);
			EXIT_ON_ERROR(hr)

				while (packetLength != 0)
				{
					// Get the available data in the shared buffer.
					hr = pCaptureClient->GetBuffer(
						&pData,
						&numFramesAvailable,
						&flags, NULL, NULL);
					EXIT_ON_ERROR(hr)

						if (flags & AUDCLNT_BUFFERFLAGS_SILENT)
						{
							pData = NULL;  // Tell CopyData to write silence.
						}
					int dataSize = numFramesAvailable * 4;//可用帧数*4=BYTE数

					for (int i = 0; i < dataSize; i++)
					{
						BYTE tem = pData[i];
						body.push_back(pData[i]);
						
					}



					hr = pCaptureClient->ReleaseBuffer(numFramesAvailable);
					EXIT_ON_ERROR(hr)

						hr = pCaptureClient->GetNextPacketSize(&packetLength);
					EXIT_ON_ERROR(hr)
				}
			counter--;
		}

	hr = pAudioClient->Stop();  // Stop recording.
	EXIT_ON_ERROR(hr)

		Exit:
	CoTaskMemFree(pwfx);
	SAFE_RELEASE(pEnumerator)
		SAFE_RELEASE(pDevice)
		SAFE_RELEASE(pAudioClient)
		SAFE_RELEASE(pCaptureClient)

		return hr;
}

void captureExample()
{
	CoInitialize(NULL);
	RecordAudioStream(body);
	CoUninitialize();



	for (int i = 0; i < body.size(); i++)
	{
		printf("%d\n", body[i]);
	}
}




using namespace std;

/*
m是长度的2^length，
dir==1时为iFFT，
dir==-1时为FFT，
complex<double> x[]为系数。
*/
void fft(int dir, long m, complex<double> x[])
{
	long i, i1, i2, j, k, l, l1, l2, n;
	complex<double> tx, t1, u, c;
	n= 1;
	for (i = 0; i < m; i++) 
		n <<= 1;//n/2^m
	
	i2 = n >> 1;
	j = 0;

	

	for(i = 0;i < n  - 1; i++)
	{
		if (i  < j)
			swap(x[i], x[j]);
		k  = i2;
		while (k  <= j)
		{
			j  -= k;
			k  >>= 1;
		}
		j  += k;
	}
	c.real(-1.0);
	c.imag(0.0);
	l2  = 1;
	for (l  = 0; l  < m; l++)
	{
		l1  = l2;
		l2  <<= 1;
		u.real(1.0);
		u.imag(0.0);
		for (j  = 0; j  < l1; j++)
		{
			for (i  = j; i  < n; i  += l2)
			{
				i1  = i  + l1;
				t1  = u  * x[i1];
				x[i1] = x[i] - t1;
				x[i] += t1;
			}
			u  = u  * c;
		}
		c.imag(sqrt((1.0 - c.real()) / 2.0));
		if (dir  == 1)
			c.imag(-c.imag());
		c.real(sqrt(1.0 + c.real()) / 2.0);
	}
	if (dir  == 1)
		for (i  = 0; i  < n; i++) x[i] /= n;
	return;
}





/*
*FFT
传入的复数数组里面都是实数，含义是多项式系数表示法的系数
系数数组长度得是2的整数次方
*/
vector<complex<double>> myFFT(vector<complex<double>> A) 
{
	const double PI = 3.141592651;
	int len = A.size();
	if (len == 1) return A;//递归结束条件
	vector<complex<double>> A1, A2;//A(x) = A1(x^2) + x * A2(x^2)
	//将系数分类
	for (int i = 0; i < len; i++)
	{
		if (i % 2 == 0)
			A1.push_back(A[i]);
		else
			A2.push_back(A[i]);
	}

	A1 = myFFT(A1);
	A2 = myFFT(A2);

	complex<double> Wn(cos(2.0*PI / len), sin(2.0*PI / len));//len等分点的角度增量
	complex<double> W(1.0, 0.0);//用于遍历复平面单位圆上的len个等分点

	for (int i = 0; i * 2 < len; i++, W *= Wn)
	{
		A[i] = A1[i] + W * A2[i];
		A[i+len/2] = A1[i] - W * A2[i];
	}
	return A;
}


void fftExample()
{
	complex<double> x[4];
	long m = 2;
	x[0].real(0.0), x[0].imag(5.0), x[1].real(1.0), x[1].imag(1.0), x[2].real(5.0), x[2].imag(7.62), x[3].real(1.0), x[3].imag(6.40);


	cout << "Before FFT" << endl;
	for (int i = 0; i < 4; i++)
	{
		cout << x[i].real() << ' ' << x[i].imag() << 'i' << endl;
	}

	//fft(-1, m, x);
	vector<complex<double>> A;
	for (int i = 0; i < 4; i++)
	{
		A.push_back(x[i]);
	}
	A = myFFT(A);
	for (int i = 0; i < 4; i++)
	{
		x[i] = A[i];
	}

	cout << "After FFT" << endl;
	for (int i = 0; i < 4; i++)
	{
		cout << x[i].real() << ' ' << x[i].imag() << 'i' << endl;
	}
	system("pause");

}



int Islittlend()
{
	int a = 0x1;
	char* b = (char*)&a; //将a的地址强转成char*类型并存于b中
	if (*b == 0x0) {
		return 0;
		//大端字节序
	}
	return 1;//小端字节序
}
int bytes2Int(BYTE higher, BYTE lower)
{
	int res = 0;
	if (Islittlend())
	{//小端序
		res = lower | higher << 8;
	}
	else
	{//大端序，按照正常顺序排列
		res = higher | lower << 8;
	}
	res -= sizeof(int) * 8;
	return res;
}



int main() 
{
	//captureExample();
	//fftExample();
	
	BYTE higher = 0;
	BYTE lower = 0;
	cout << Islittlend() << endl;
	cout << bytes2Int(higher, lower) << endl;

	unsigned short int a = 50000;
	signed short int b = 0;
	b = a;
	cout << "无符号数转为有符号数: " << b << endl;
	cout << sizeof(int)*8 << endl;


	return 0;
}